'''
Created on 8 Nov 2014

@author: User
'''
import numpy as np

def getRSI(prices,period=14):
    num_prices = len(prices)
    
    if num_prices < period:
        # show error message
        raise SystemExit('Error: num_prices < period')
    
    # this could be named gains/losses to save time/memory in the future
    changes = prices[1:] - prices[:-1]
    #num_changes = len(changes)

    rsi_range = num_prices - period
    
    rsis = np.zeros(rsi_range)
    
    gains = np.array(changes)
    # assign 0 to all negative values
    masked_gains = gains < 0
    gains[masked_gains] = 0
    
    losses = np.array(changes)
    # assign 0 to all positive values
    masked_losses = losses > 0
    losses[masked_losses] = 0
    # convert all negatives into positives
    losses *= -1
    
    avg_gain = np.mean(gains[:period])
    avg_loss = np.mean(losses[:period])
    
    if avg_loss == 0:
        rsis[0] = 100
    else:
        rs = avg_gain / avg_loss
        rsis[0] = 100 - (100 / (1 + rs))
    
    for idx in range(1, rsi_range):
        avg_gain = ((avg_gain * (period - 1) + gains[idx + (period - 1)]) /
                    period)
        avg_loss = ((avg_loss * (period - 1) + losses[idx + (period - 1)]) /
                    period)
    
        if avg_loss == 0:
            rsis[idx] = 100
        else:
            rs = avg_gain / avg_loss
            rsis[idx] = 100 - (100 / (1 + rs))
    
    return rsis
    
def getSMA(prices,n):
    weights = np.repeat(1.0,n)/n;
    smas = np.convolve(prices,weights,"valid");
    return smas;

def getExMA(prices,n):
    weights = np.exp(np.linspace(01.,0.,n));
    weights /= weights.sum();
    a =np.convolve(prices,weights,mode="full")[:len(prices)];
    a[:n] = a[n];
    return a;

def getMFI(stock,period,prices):
    rawmoney = [];
    mfis=[];
    for i in range(len(prices.closes)):
        posSum=0.;
        negSum=0.;
        tp = (prices.highs[i]+prices.lows[i]+prices.closes[i])/3.;
        rawmoney.append(tp*prices.volumes[i]);
      
    for n in range(len(prices.closes)-period):
        mfis.append(__getMFR(rawmoney, period, n));
       
    #else:
        #mfis.append(50);
    #mfis.append(50);
    print("MFI Length: " +str(len(mfis)));
    return mfis;        
    #print("MFI: " +str(mfis));
    
def __getMFR(rawmoney,period,start):
    pm=0.;
    nm=0.;
    end = start-period;
    #print("start {0} end: {1} rawleng: {2}".format(start,end,len(rawmoney)));
    length= end-start;
    #print(length)
    for i in range(start,end,-1):
          
        if rawmoney[i]>rawmoney[i-1]:
            pm+=rawmoney[i];
        else: nm+=rawmoney[i];
  
    return 100 * (pm/(pm+nm));
        